package de.koller.balance.render;

import de.koller.aframe.gl.AFrame;
import de.koller.aframe.gl.Camera;
import de.koller.aframe.gl.Utils;
import de.koller.aframe.util.filter.DownSample;
import de.koller.balance.BNode;
import de.koller.balance.render.texture.Textures;
import de.koller.oceanFramework.gl.OceanGame;
import de.koller.oceanFramework.gl.util.ImagePreview;
import de.koller.oceanFramework.gl.util.ParticleTexture;
import de.koller.oceanFramework.gl.util.ViewUtil;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import org.lwjgl.opengl.GL11;
import org.lwjgl.util.glu.GLU;

public class BRender extends BNode {
	
	public boolean useHighAntialias = false;
	
	public final int screenW = 1920 / 4, screenH = 1080 / 4;
	public final Textures textures = new Textures();
	public final Camera camera = new Camera();

	public AFrame frame = new AFrame( screenW*(useHighAntialias?6:3), screenH*(useHighAntialias?6:3) );
	private ParticleTexture out;
	private ParticleTexture glowTexture;
	
	private ParticleTexture frameDown;
	private ParticleTexture frameTexture;
	private ParticleTexture frameLight;
	private ParticleTexture frameLightDown;
	
	@Override
	protected void init() {
		super.init();

		out = ParticleTexture.generate( screenW, screenH );
		frameDown = ParticleTexture.generate( screenW, screenH );
		frameTexture = ParticleTexture.generate( screenW*(useHighAntialias?6:3), screenH*(useHighAntialias?6:3) );
		frameLight = ParticleTexture.generate( screenW*(useHighAntialias?6:3), screenH*(useHighAntialias?6:3) );
		glowTexture = ParticleTexture.generate( screenW, screenH );
		frameLightDown = ParticleTexture.generate( screenW, screenH );
		frame.setUp();
		
//		GL11.glEnable( GL11.GL_CULL_FACE );
//		GL11.glCullFace( GL11.GL_BACK );

		GL11.glEnable( GL11.GL_DEPTH_TEST );
		GL11.glDepthFunc( GL11.GL_LEQUAL );
		
		GL11.glAlphaFunc( GL11.GL_GREATER, 0.01f );
		GL11.glEnable( GL11.GL_ALPHA_TEST );
	}
	
	public void perspectiveSet() {
		GL11.glMatrixMode( GL11.GL_PROJECTION );
		GL11.glLoadIdentity();

		GLU.gluPerspective( 60.0f, (float)screenW/(float)screenH, 0.001f, 2000.0f );
		
		GL11.glMatrixMode( GL11.GL_MODELVIEW );
		GL11.glLoadIdentity();
	}
	
	public void orthoSet() {
		GL11.glMatrixMode( GL11.GL_PROJECTION );
		GL11.glLoadIdentity();

		GL11.glOrtho( 0, screenW, screenH, 0, -1000, 1000 );
		
		GL11.glMatrixMode( GL11.GL_MODELVIEW );
		GL11.glLoadIdentity();
	}
	
	public void renderGame( int elapsedTime ) {		
		//GL11.glTexParameteri( GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP );
		//GL11.glTexParameteri( GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_CLAMP );
		GL11.glClearColor( 0, 0, 0, 1 );
		GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT | GL11.GL_STENCIL_BUFFER_BIT);
		
		GL11.glHint( GL11.GL_PERSPECTIVE_CORRECTION_HINT, GL11.GL_NICEST );
		GL11.glHint( GL11.GL_LINE_SMOOTH_HINT, GL11.GL_NICEST );
		GL11.glHint( GL11.GL_POLYGON_SMOOTH_HINT, GL11.GL_NICEST );
		GL11.glHint( GL11.GL_POINT_SMOOTH_HINT, GL11.GL_NICEST );
		
		//GL11.glEnable( GL11.GL_BLEND );
		//GL11.glBlendFunc( GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA );
		
		if( !broot.quality ) {
			renderSzene( false );
			return;
		}
		
		// --- Frame
		frame.bind();
		renderSzene( false );
		frame.unbind();
		
		frame.bindTexture();
		Utils.loadTextureData( frameTexture );
		
		// --- Light
		frame.bind();
		renderSzene( true );
		frame.unbind();
		
		frame.bindTexture();
		Utils.loadTextureData( frameLight, screenW*3, screenH*3 );
		
		// ---
		DownSample.use( frameTexture, frameDown );
		frameDown.flush();
		
		DownSample.use( frameLight, frameLightDown );
		frameLightDown.flush();
		
		ImagePreview.showRaster( frameDown, screenW, screenH );
		ImagePreview.showRaster( frameLightDown, screenW, screenH );
		
		System.arraycopy( frameDown.getData(), 0, out.getData(), 0, out.getData().length );
		out.flush();
		
		//Glow.use( frameLightDown, glowTexture );
		//Combine.max( frameDown, glowTexture, out );
		renderFrame();
		
		OceanGame.checkForErrorGL( "GLError" );
	}

	private void renderSzene( boolean light ) {
		//perspectiveSet();
		
		//GL11.glPushMatrix();
		//broot.scene.setupCamera( camera );
		//camera.transformGL();
		
		if( !light ) {
			if( broot.quality )
				broot.scene.renderSzeneQuality();
			else
				broot.scene.renderSzenePreview();
		} else
			broot.scene.renderLight();
		
		//GL11.glPopMatrix();
	}

	private void renderFrame() {
		orthoSet();
		GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT | GL11.GL_STENCIL_BUFFER_BIT);
		//frame.renderScreen();
		frameTexture.bind();
		GL11.glColor3f( 1, 1, 1 ); 
		ViewUtil.draw2D( 0, 0, screenW, screenH, 0 );
		
		if( broot.quality ) {
			System.out.println( "fertig" );
			//ImagePreview.showRaster( frameTexture, 800, 600 );
			//ImagePreview.showRaster( glowTexture, 800, 600 );
			ImagePreview.showRaster( out, screenW, screenH );
			writeOut();
			broot.quality = false;
		}
	}
	
	private void writeOut() {
		BufferedImage i = new BufferedImage( out.getWidth(), out.getHeight(), BufferedImage.TYPE_INT_ARGB );
		
		for( int x = 0; x < i.getWidth(); x++ )
			for( int y = 0; y < i.getHeight(); y++ )
				i.setRGB( x, y, out.colorAt( x, y ) );
		
		try {
			ImageIO.write( i, "png", new File( "./screenshots/renderedImage.png" ) );
		} catch( IOException ex ) {
			System.err.println( ex );
		}
	}
	
}
